using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Configuration;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Reflection;
using System.Runtime.Remoting.Messaging;
using System.Text;
using System.Threading;
using System.Windows.Forms;
using SqlRunner;
using SqlRunner.controls;
using SqlRunner.Readers;
using SqlRunner.uiStatus;
using SQLRunnerLib.DB;
using SQLRunnerLib.Project;
using SQLRunnerLib.Services;
using SQLRunnerLib.Util;
using SQLRunnerLib.VersionCheck;
using SQLServices.Log;
using SQLServices.TransMgr;

namespace SqlRunner
{
	/// <summary>
	/// Summary description for Form1.
	/// </summary>
	public partial class FormMain : Form
	{
		#region Private Members

		#region Private Instances

		static frmSplash splashForm;
		static frmCheckNewVersion checkVersionForm;
		private RunnerSettings AppSettings;
		private int errorCounter = 0;
		private int totalCounter = 0;

		private MainFormStatus applicationStatus = MainFormStatus.Initial;
		private readonly Groups<MainFormStatus> applicationGroups = new Groups<MainFormStatus>();
		private MainFormStatus projectStatus = MainFormStatus.Initial;
		private MainFormStatus prevFolderStatus = MainFormStatus.Initial;
		private readonly Groups<MainFormStatus> folderGroups = new Groups<MainFormStatus>();
		private readonly FormMainController controller;

		#endregion
		#region Icons
		// TODO: Load icons from resource file or something similar
		private Icon I_FOLDER;
		private Icon I_FOLDER_C;
		private Icon I_FOLDER_OPEN;
		private Icon I_FOLDER_OPEN_C;
		private Icon I_FILE;
        private Icon I_FILE_C;				

		#endregion
		
        //private enum IconList
        //{
        //    Folder = 0,
        //    Folder_Cancelled = 1,
        //    File = 2,
        //    File_Cancelled = 3,
        //    Folder_Open = 4,
        //    Folder_Open_Cancelled = 5
        //}

		#endregion
		#region Public Methods

		public void StartSplash()
		{
			// Instance a splash form given the image names
			splashForm = new frmSplash(this);

			// Run the form: Displaying the form is not enough
			Application.Run(splashForm);
            //splashForm.Show(this);
			
		}

		public FormMain()
		{
		    Thread splashThread = new Thread(StartSplash);
			splashThread.Start();
			
			//
			// Required for Windows Form Designer support
			//
			InitializeComponent();

			// EA0908: Icon initialization
            InitializeIcons();

			timerExecution = new TimerExtended(components);
			timerExecution.Tick += timerExecution_Tick;
			// Check the version
			CheckForNewVersion();
			Thread.Sleep(2000);
		}

	    public FormMain(FormMainController controller):this() {
			this.controller = controller;
			controller.FormInstance = this;
		}
		#endregion
		#region Protected Methods

		/// <summary>
		/// Clean up any resources being used.
		/// </summary>
		protected override void Dispose( bool disposing )
		{
			if( disposing )
			{
				if (components != null) 
				{
					components.Dispose();
				}
			}
			base.Dispose( disposing );
		}

		// Close Splash screen is still open
		protected override void OnVisibleChanged(EventArgs e)
		{
			base.OnVisibleChanged (e);
			if (splashForm != null & Visible) CloseSplash();
		}

		#endregion
		#region Private Methods

		#region UI Methods

		#region Form events

		private void frmMain_Load(object sender, EventArgs e)
		{
            InitialiseNewProject();
			stsBar.ShowPanels = true;
			Text = "SQL Server Runner - [" + ProductVersion + "]";
			// Check for Properties file
            string filePath = ConfigurationManager.AppSettings.Get("RunnerPropertiesFile").ToString();
			FileInfo file = new FileInfo(filePath);
			if (file.Exists) 
			{
				AppSettings = RunnerSettings.Deserialize(file.Name);
				RunnerProperties properties = AppSettings.FindSetPropertiesByKeyField(AppSettings.defaultProperties);
				RunnerProperty property = properties.FindProperty("servername");
			}
			else
			{
				AppSettings = new RunnerSettings();
			}
			SetGroups();
		}

		private void FormMain_Closing(object sender, CancelEventArgs e)
		{
			if ( applicationStatus == MainFormStatus.Executing | 
				applicationStatus == MainFormStatus.Cancel )
			{
				DialogResult result = MessageBox.Show(
					"Some scripts are being processed at this moment, " + 
					"do you want to finish the application?",
					"Exit SQL Runner",
					MessageBoxButtons.YesNo,
					MessageBoxIcon.Hand);

				if ( result == DialogResult.No )
				{
					e.Cancel = true;
				}
				else
				{
					btnAbort_Click(this, new EventArgs());
					Thread.Sleep(5000);
					controller.AbortRunner();
				}
			}

            if (ProjectStatus == MainFormStatus.Dirty &&
                MessageBox.Show("Do you want to save project changes?", "Save Project",
                MessageBoxButtons.YesNo, MessageBoxIcon.Asterisk) == DialogResult.Yes)
            {
                if (!SaveProject(false))
                    e.Cancel = true;
            }
        }

		#endregion
		#region Command Buttons

		private void btnAbort_Click(object sender, EventArgs e)
		{
		    if (applicationStatus != MainFormStatus.Executing) return;
		    setComment("Waiting for SQL Server to finish executing current script to close the connection to the server ... please wait");
		    controller.CancelRunner();
		    btnAbort.Enabled = false;
		}

		private void btnRun_Click(object sender, EventArgs e)
		{
            try
            {
                SQLProject project = controller.RefreshSQLProject(lstFolders, this);

                SQLEnvironment selectedEnvironment = controller.Project.SelectedEnvironment;
                if (!selectedEnvironment.Trusted && !selectedEnvironment.SavePassword && string.IsNullOrEmpty(selectedEnvironment.Password))
                {
                    frmPassword passwordForm = new frmPassword(selectedEnvironment);
                    if (passwordForm.ShowDialog(this) == DialogResult.Cancel)
                    {
                        return;
                    }
                    try
                    {
                        selectedEnvironment.TestConnection();
                    }
                    catch (Exception ex)
                    {
                        selectedEnvironment.Password = string.Empty;
                        MessageBox.Show(ex.Message, "Error");
                        return;
                    }
                }

                if (project.Folders.Count == 0)
                    return;

                selectedEnvironment.ConnectToDatabase();
                controller.WriteProperties(AppSettings, selectedEnvironment.ServerName, selectedEnvironment.DatabaseName, selectedEnvironment.Username);
                this.Cursor = Cursors.WaitCursor;
                ApplicationStatus = MainFormStatus.Executing;
                prevFolderStatus = ProjectStatus;
                ProjectStatus = MainFormStatus.Executing;
                totalCounter = 0;
                errorCounter = 0;
                updateCounters();
                controller.Project = project;
                progressBar.Maximum = controller.TotalFiles();
                controller.runScripts(selectedEnvironment);
                ServiceContainer.Instance.Logger.LogMessage("btnRun - formMain-Run thread has started");
                Cursor = Cursors.Default;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "Error");
            }
		}

	    private void btnClear_Click(object sender, EventArgs e)
		{
            ServiceContainer.Instance.EventLogger.Reset();
			refreshTree();
		}

		private void btnSQL_Click(object sender, EventArgs e)
		{
			bool errorFlag = false;
			if (treeScripts.SelectedNode == null) return;
			if (treeScripts.SelectedNode.Tag == null) return;
			SQLUtil sqlApp = new SQLUtil();
            int version = ServiceContainer.Instance.SQLConnection.VersionMajor;
			string app = sqlApp.SqlApplicationFactory(version);

            SQLEnvironment selectedEnvironment = controller.Project.SelectedEnvironment;
			string arg = sqlApp.SqlArgumentFactory(version, 
				new SQLArguments(selectedEnvironment.ServerName,
                                  selectedEnvironment.DatabaseName,
                                  selectedEnvironment.Username,
                                  selectedEnvironment.Password, 
								  selectedEnvironment.Trusted, 
								  ((IItemLog) treeScripts.SelectedNode.Tag).Path.FullPath() + @"\" + treeScripts.SelectedNode.Text));
				
			try
			{
				Process.Start(app, arg );
			}
			catch(Exception exp)
			{
				MessageBox.Show(this, String.Format("An error took place when SQL Query application was called: {0}", exp.Message));
				errorFlag = true;
			}

			if ( errorFlag )
			{
				openWithNotepad(((IItemLog) treeScripts.SelectedNode.Tag).Path.FullPath() 
					+ @"\" + treeScripts.SelectedNode.Text);
			}
		}

        private void tlBtnAddFolder_Click(object sender, EventArgs e)
        {
            FolderAdd();
        }

        private void tlBtnRemove_Click(object sender, EventArgs e)
        {
            FolderRemove();
        }

        private void tlBtnUp_Click(object sender, EventArgs e)
        {
            FolderUp();
        }

        private void tlBtnDown_Click(object sender, EventArgs e)
        {
            FolderDown();
        }

        private void tlBtnClear_Click(object sender, EventArgs e)
        {
            FolderClear();
        }

	    #endregion
		#region Other Controls

		private void treeScripts_AfterSelect(object sender, TreeViewEventArgs e)
		{
            ServiceContainer.Instance.Logger.LogMessage("TreeScripts - After Select was started");
			if (treeScripts.SelectedNode != null)
			{
				if (treeScripts.SelectedNode.Tag != null)
				{
					IItemLog log = (IItemLog) treeScripts.SelectedNode.Tag;
					String[] strPhrases = log.Error.Split((char) 10);
					StringBuilder strBuilder = controller.ParseErrorMessage(strPhrases);
					txtEventError.Text = strBuilder.ToString();
					txtEventName.Text = log.Name;
				}
			}
            ServiceContainer.Instance.Logger.LogMessage("TreeScripts - After Select has finished");
		}

		private void treeScripts_DoubleClick(object sender, EventArgs e)
		{
			btnSQL_Click(sender, e);	
		}

		private void lstFolders_DragDrop(object sender, DragEventArgs e)
		{
			IFolderReader reader = ReaderFactory.GetReader(e.Data);
			List<string> folders = reader.ReadFolders(e);
			controller.AddFoldersToListBox(folders, lstFolders);
		}

		private void lstFolders_DragEnter(object sender, DragEventArgs e)
		{
			if (e.Data.GetDataPresent(DataFormats.CommaSeparatedValue) |
				e.Data.GetDataPresent(DataFormats.FileDrop))
			{
				e.Effect = DragDropEffects.Copy;
			}
			else
			{
				e.Effect = DragDropEffects.None;
			}
		}

		#endregion
		#region Menus

		private void mnuReset_Click(object sender, EventArgs e){
            ServiceContainer.Instance.SQLConnection.Reset();
			ApplicationStatus = MainFormStatus.Initial;
		}

		private void mnuExit_Click(object sender, EventArgs e){	
			Close();		
		}
		
		private void menuItem2_Click(object sender, EventArgs e){
			frmAbout aform = new frmAbout();
			aform.ShowDialog(this);
		}

		private void mnuOpen_Click(object sender, EventArgs e){
			CheckIfIsDirty();
			openFile.CheckPathExists = true;
			openFile.Filter = "SQL Runner (*.sqlrunner)|*.sqlrunner";
			if (openFile.ShowDialog(this) == DialogResult.OK) {
				clearFolders();
				chkSubFolders.Checked = false;
				controller.OpenSQLProject(openFile.FileName, this);
				ProjectStatus = MainFormStatus.Initial;
			}
		}

		private void RefreshWindowTitle() {
			Text = "SQL Server Runner - [" + 
				ProductVersion + "]";
			if (controller.Project != null)
			{
				Text +=  " - " + controller.Project.FileFullPath();
				if (ProjectStatus == MainFormStatus.Dirty) 
				{
					Text += "*";
				}
			}
		}

		private void mnuSave_Click(object sender, EventArgs e){
            SaveProject(false);
        }

		private void mnuSaveAs_Click(object sender, EventArgs e){
            SaveProject(true);
		}
		
		private void mnuNew_Click(object sender, EventArgs e)
		{
            InitialiseNewProject();
		}

		#endregion
		#region Check Boxes

		private void chkSubFolders_CheckedChanged(object sender, EventArgs e)
		{
			for (int i=0; i < lstFolders.Items.Count; i++)
			{
				lstFolders.SetItemChecked(i, chkSubFolders.Checked);
				ProjectStatus = MainFormStatus.Dirty;
			}
            controller.RefreshSQLProject(lstFolders, this);
        }
		#endregion
        #region Icons
        private enum TreeImages
        {
            Folder,
            FolderCancelled,
            File,
            FileCancelled,
            FolderOpen,
            FolderOpenCancelled
        }

        private void InitializeIcons()
        {
            InitializeTreeIcons();
            InitializeScriptsIcons();

            var appPath = Application.StartupPath;
            tsEnvironments.ImageList = new ImageList();
            tsEnvironments.ImageList.Images.Add("add", new Icon(Path.Combine(appPath, @"images\add_environment.ico")));
            btnAddEnvironment.ImageKey = "add";
            tsEnvironments.ImageList.Images.Add("remove", new Icon(Path.Combine(appPath, @"images\remove_environment.ico")));
            btnDeleteEnvironment.ImageKey = "remove";
            tsEnvironments.ImageList.Images.Add("edit", new Icon(Path.Combine(appPath, @"images\edit_environment.ico")));
            btnEditEnvironment.ImageKey = "edit";
        }

        private void InitializeScriptsIcons()
        {
            var appPath = Application.StartupPath;
            tsScripts.ImageList = new ImageList();

            tsScripts.ImageList.Images.Add("arrow_down", new Icon(Path.Combine(appPath, @"images\arrow_down.ico")));
            tsScripts.ImageList.Images.Add("arrow_up", new Icon(Path.Combine(appPath, @"images\arrow_up.ico")));
            tsScripts.ImageList.Images.Add("add_folder", new Icon(Path.Combine(appPath, @"images\add_folder.ico")));
            tsScripts.ImageList.Images.Add("remove_folder", new Icon(Path.Combine(appPath, @"images\remove_folder.ico")));
            tsScripts.ImageList.Images.Add("clear", new Icon(Path.Combine(appPath, @"images\clear.ico")));
            tlBtnDown.ImageKey = "arrow_down";
            tlBtnUp.ImageKey = "arrow_up";
            tlBtnAddFolder.ImageKey = "add_folder";
            tlBtnRemove.ImageKey = "remove_folder";
            tlBtnClear.ImageKey = "clear";
        }

        private void InitializeTreeIcons()
        {
            treeScripts.ImageList = new ImageList();
            var appPath = Application.StartupPath;
            treeScripts.ImageList.Images.Add(
                TreeImages.Folder.ToString(),
                new Icon(Path.Combine(appPath, @"images\folder.ico")));

            treeScripts.ImageList.Images.Add(
                TreeImages.FolderCancelled.ToString(),
                new Icon(Path.Combine(appPath, @"images\folder_cancelled.ico")));

            treeScripts.ImageList.Images.Add(
                TreeImages.File.ToString(),
                new Icon(Path.Combine(appPath, @"images\sqlfile.ico")));

            treeScripts.ImageList.Images.Add(
                TreeImages.FileCancelled.ToString(),
                new Icon(Path.Combine(appPath, @"images\sqlfile_cancelled.ico")));

            treeScripts.ImageList.Images.Add(
                TreeImages.FolderOpen.ToString(),
                new Icon(Path.Combine(appPath, @"images\folder_open.ico")));

            treeScripts.ImageList.Images.Add(
                TreeImages.FolderCancelled.ToString(),
                new Icon(Path.Combine(appPath, @"images\folder_open_cancelled.ico")));
        }

        #endregion

        #endregion

        #region Internal Properties

        internal MainFormStatus ApplicationStatus
		{
			get
			{
				return applicationStatus;
			}
			set
			{
				applicationStatus = value;
				applicationGroups.UpdateStatus(value);
			}
		}

		private MainFormStatus ProjectStatus {
			get { return projectStatus; }
			set {
				prevFolderStatus = projectStatus;
				projectStatus = value;
				folderGroups.UpdateStatus(value);
				RefreshWindowTitle();
			}
		}

		public MainFormStatus PrevFolderStatus {
			get { return prevFolderStatus; }
		}

	    public ConnectionMgrType ConnectionMgrMode
	    {
	        get { return _connMgrType; }
	    }

	    #endregion

		#region Helper Methods
		
		#region Internal Methods

		internal void increaseTotalCounter()
		{
            ServiceContainer.Instance.Logger.LogMessage("increaseTotalCounter was called");
			totalCounter++;
			updateCounters();
		}

		internal void increaseErrorCounter()
		{
            ServiceContainer.Instance.Logger.LogMessage("increaseErrorCounter was called");
			errorCounter++;
			updateCounters();
		}

		internal void addLog(IItemLog item)
		{
            ServiceContainer.Instance.Logger.LogMessage("AddLog method was called");
			logItem(item);
		}

        internal void changeAppStatus(MainFormStatus status)
        {
            ApplicationStatus = status;  
        }

        internal void changeProjectStatus(MainFormStatus status)
        {
            ProjectStatus = status;
        }

        internal void setComment(string comment)
        {
            setComment(comment, new object[] { });
        }

		internal void setComment(string format, params object[] args)
		{
            ServiceContainer.Instance.Logger.LogMessage("setComment method was called");
			txtComment.Text = String.Format(format, args);
		}

        internal bool runScriptButtonEnabled
        {
            set { btnRun.Enabled = value; }
        }
		
		internal void addFolder(string folder, bool isChecked) {
			lstFolders.Items.Add(folder, isChecked);
		}

		internal void clearFolders() {
			lstFolders.Items.Clear();
		}
        internal void clearEnvironments() {
            lvEnvironments.Items.Clear();
        }

		#endregion

		#region Private Methods

        #region Folder Methods
        private void FolderAdd()
        {
            RunnerProperties properties = AppSettings.DefaultSetProperties();
            RunnerProperty property = properties != null ? properties.FindProperty("path") : null;
            DirectoryInfo aDir;
            if (property != null && property.value.Length > 0)
            {
                aDir = new DirectoryInfo(property.value);
                if (aDir.Exists) fBrowser.SelectedPath = property.value;
            }
            if (fBrowser.ShowDialog(this) == DialogResult.OK && fBrowser.SelectedPath.Length > 0)
            {
                aDir = new DirectoryInfo(fBrowser.SelectedPath);
                List<string> folderPaths = new List<string>();
                folderPaths.Add(aDir.FullName);
                controller.AddFoldersToListBox(folderPaths, lstFolders);
                
                if (property != null) property.value = fBrowser.SelectedPath;
                FormMainController.LastPath = fBrowser.SelectedPath;
            }
            else
            {
                if (lstFolders.Items.Count == 0)
                {
                    btnRun.Enabled = false;
                    txtComment.Text = "Select folder(s) to run scripts from";
                }
            }
            controller.RefreshSQLProject(lstFolders, this);
        }

        private void FolderDown()
        {
            //TODO: This method always unchecks the box and it shouldn't.
            if (lstFolders.SelectedItem == null || (lstFolders.SelectedIndex + 1) >= lstFolders.Items.Count) return;
            int index = lstFolders.SelectedIndex;
            string item = (string)lstFolders.SelectedItem;
            lstFolders.Items.RemoveAt(index);
            index++;
            lstFolders.Items.Insert(index, item);
            lstFolders.SelectedIndex = index;
            ProjectStatus = MainFormStatus.Dirty;
            controller.RefreshSQLProject(lstFolders, this);
        }

        private void FolderUp()
        {
            //TODO: This method always unchecks the box and it shouldn't
            if (lstFolders.SelectedItem == null || lstFolders.SelectedIndex <= 0) return;
            int index = lstFolders.SelectedIndex;
            string item = (string)lstFolders.SelectedItem;
            lstFolders.Items.RemoveAt(index);
            index--;
            lstFolders.Items.Insert(index, item);
            lstFolders.SelectedIndex = index;
            ProjectStatus = MainFormStatus.Dirty;
            controller.RefreshSQLProject(lstFolders, this);
        }

        private void FolderClear()
        {
            lstFolders.Items.Clear();
            controller.RefreshSQLProject(lstFolders, this);
        }

        private void FolderRemove()
        {
            if (lstFolders.SelectedItem == null) return;
            lstFolders.Items.Remove(lstFolders.SelectedItem);
            ProjectStatus = MainFormStatus.Dirty;
            controller.RefreshSQLProject(lstFolders, this);
        }

        #endregion
        private void InitialiseNewProject()
        {
            CheckIfIsDirty();
            clearFolders();
            clearEnvironments();
            chkSubFolders.Checked = false;
            SQLProject proj = new SQLProject();
            proj.Extensions.Add("sql");
            controller.Project = proj;
            ProjectStatus = MainFormStatus.Initial;
        }

        private bool SaveProject(bool saveAs)
        {
            if (lstFolders.Items.Count == 0)
            {
                MessageBox.Show("Please select some folder/s before you try to save the project",
                    "Save Project", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                return false;
            }

            if (controller.Project.FileFullPath().Equals(string.Empty) ||
                !File.Exists(controller.Project.FileFullPath()) || saveAs)
            {
                saveFile.CheckPathExists = true;
                saveFile.AddExtension = true;
                saveFile.Filter = "SQL Runner (*.sqlrunner)|*.sqlrunner";
                if (saveFile.ShowDialog(this) == DialogResult.OK)
                {
                    ClearNonSavedPasswords();
                    controller.RefreshSQLProject(lstFolders, this).Serialize(saveFile.FileName);
                    ProjectStatus = MainFormStatus.Initial;
                    return true;
                }
            }
            else
            {
                ClearNonSavedPasswords();
                controller.RefreshSQLProject(lstFolders, this).Serialize(controller.Project.FileFullPath());
                ProjectStatus = MainFormStatus.Initial;
                return true;
            }

            return false;
        }

        private void ClearNonSavedPasswords()
        {
            foreach (SQLEnvironment env in controller.Project.Environments)
            {
                if (!env.SavePassword)
                {
                    env.Password = string.Empty;
                }
            }
        }

        private void SetGroups()
		{
            GroupControls<MainFormStatus> g = new GroupControls<MainFormStatus>("Enabled", MainFormStatus.DbSelected);
			g.AddControl(btnRun);
			g.AddControl(grpEvent);
			g.AddControl(btnClear);
			g.AddControl(grpSQLPath);
			g.AddControl(mnuReset);
			applicationGroups.AddGroup(g);

            g = new GroupControls<MainFormStatus>("Enabled", MainFormStatus.DbSelected | MainFormStatus.Initial | MainFormStatus.Connected);
            g.AddControl(mnuConnMgr);
            applicationGroups.AddGroup(g);

            g = new GroupControls<MainFormStatus>("Enabled", MainFormStatus.DbSelected | MainFormStatus.Executing);
			g.AddControl(grpScriptList);
			applicationGroups.AddGroup(g);

            g = new GroupControls<MainFormStatus>("Visible", MainFormStatus.Executing | MainFormStatus.Cancel);
			g.AddControl(progressPane);
			applicationGroups.AddGroup(g);

            g = new GroupControls<MainFormStatus>("Enabled", MainFormStatus.Executing | MainFormStatus.Cancel);
			g.AddControl(timerExecution);
			applicationGroups.AddGroup(g);

            g = new GroupControls<MainFormStatus>("Enabled", MainFormStatus.Executing);
			g.AddControl(btnAbort);
			applicationGroups.AddGroup(g);

			// Folder Status
            g = new GroupControls<MainFormStatus>("Enabled", MainFormStatus.Initial | MainFormStatus.Dirty);
			g.AddControl(mnuOpen);
			g.AddControl(mnuSaveAs);
			g.AddControl(mnuNew);
			folderGroups.AddGroup(g);

            g = new GroupControls<MainFormStatus>("Enabled", MainFormStatus.Dirty);
			g.AddControl(mnuSave);
			folderGroups.AddGroup(g);
		}

		private void updateCounters()
		{
            ServiceContainer.Instance.Logger.LogMessage("updateCounters was called");
			progressBar.Value = totalCounter <= progressBar.Maximum ? 
				totalCounter : progressBar.Maximum;
			txtTotal.Text = "Scripts: " + totalCounter;
			txtTotalErrors.Text = "Errors: " + errorCounter;
		}

		private void refreshTree()
		{
			treeScripts.Nodes.Clear();
			txtEventName.Text ="";
			txtEventError.Text ="";
		}

		private void logItem(IItemLog log)
		{
			//log.Path.RefreshNextNode(null);
			TreeNode parentNode = 
				controller.GetParentNode(treeScripts.Nodes, log.Path.FirstNode());
			if ( parentNode.ImageIndex == -1 )
			{
                // EA0908: Use an enumeration instead of an index
                //parentNode.ImageIndex = (int) IconList.Folder;
                //parentNode.SelectedImageIndex = (int)IconList.Folder_Open;
                parentNode.ImageKey = TreeImages.Folder.ToString();
			    parentNode.SelectedImageKey = TreeImages.FolderOpen.ToString();
				
			}
			TreeNode node = new TreeNode(log.Name)
			                    {
			                        Tag = log, 
                                    ImageKey = TreeImages.File.ToString()
			                    };

            node.SelectedImageKey = TreeImages.File.ToString();
			parentNode.Nodes.Add(node);
			if (log.Type == EventType.ERROR)
				errorInNode(node);
		}
		
		private void errorInNode(TreeNode node)
		{
			node.ForeColor = Color.Red;
			if (node.Tag == null)
			{
                // EA0908: Replace the index by an enumeration
                //node.ImageIndex = (int) IconList.Folder_Cancelled;
                //node.SelectedImageIndex = (int) IconList.Folder_Open_Cancelled;
			    node.ImageKey = TreeImages.FolderCancelled.ToString();
			    node.SelectedImageKey = TreeImages.FolderOpenCancelled.ToString();
			}
			else
			{
			    // EA0908: Replace the index by an enumeration
                //node.ImageIndex = (int) IconList.File_Cancelled;				
                node.ImageKey = TreeImages.FileCancelled.ToString();
                node.SelectedImageKey = TreeImages.FileCancelled.ToString();
			}
			if (node.Parent != null) errorInNode(node.Parent);
		}

        //private void connectToDB(string dbName)
        //{
        //    setComment("connecting to {0} database", dbName);
        //    ServiceContainer.SQLConnection.GetDatabase(dbName);
        //    setComment("Select folder with scripts to run","");
        //    ApplicationStatus = Status.DbSelected;
        //}

		private void openWithNotepad(string path)
		{

			DialogResult result = MessageBox.Show("Do you want to open the script in notepad?", "Opening script", 
				MessageBoxButtons.YesNo, MessageBoxIcon.Asterisk);
			if ( result == DialogResult.Yes )
			{
			    string app = "notepad.exe";
				string arg = path;
				try
				{
					Process.Start(app, arg);
				}
				catch (Exception exp)
				{
					MessageBox.Show(this, String.Format("An error took place when the notepad was called: {0}", exp.Message));
				}
			}
		}

		private void timerExecution_Tick(object sender, EventArgs e)
		{
			txtElapsedTime.Text = String.Format("Elapsed Time: {0}",
				timerExecution.ElapsedTime);
		}

		private void CloseSplash()
		{
			if ( splashForm == null ) return;
			// Shut down the splash screen
			splashForm.Invoke(new EventHandler(splashForm.KillMe));
			splashForm.Dispose();
			splashForm = null;
		}

		private void CheckIfIsDirty() 
		{
			if (ProjectStatus == MainFormStatus.Dirty &&
				MessageBox.Show("Do you want to save project changes?", "Save Project", 
				MessageBoxButtons.YesNo, MessageBoxIcon.Asterisk) == DialogResult.Yes) 
			{
				SaveProject(false);
			}
		}

		#endregion

		#endregion

		#region Check For New Version
		
		private void CheckForNewVersion()
		{
			bool flag = bool.Parse(ConfigurationSettings.AppSettings.Get("CheckForNewVersion"));
			if ( !flag ) return;
			URLChecker checker = new URLChecker();
			CheckVersionHandler checkerCall = new CheckVersionHandler(checker.CheckVersion);
			checkerCall.BeginInvoke(
				ConfigurationSettings.AppSettings.Get("NewVersionUrl"), 
				Assembly.GetExecutingAssembly().GetName().Version, 
				new AsyncCallback(AsyncCheckVersion), null);
		}

		private void AsyncCheckVersion(IAsyncResult receipt)
		{
			AsyncResult result = (AsyncResult)receipt;
			//  retrieve the calling delegate
			CheckVersionHandler checkerCall = (CheckVersionHandler)result.AsyncDelegate;
			//  Retrieve our results; this is guaranteed not to block, as the async op is complete
			SQLRunnerVersion webVersion = checkerCall.EndInvoke(receipt);
			if ( webVersion != null )
			{
				bool flag = webVersion.Version.CompareTo(
								AppVersion.ConvertFromSystemVersion(
									Assembly.GetExecutingAssembly().GetName().Version)) > 0;
				if ( !flag ) return;
				checkVersionForm = 
					new frmCheckNewVersion(
					webVersion.MsiUrl, 
					AppVersion.TransforToSystemVersion(webVersion.Version),
					webVersion.LinkText);
				Application.Run(checkVersionForm);
			}
		}
		
		#endregion

        #region "Connection Manager Menus"

        private ConnectionMgrType _connMgrType = ConnectionMgrType.PessimistConnMgr;
        private void mnuPessimisticMgr_Click(object sender, EventArgs e)
        {
            setConnMgr(mnuPessimisticMgr, ConnectionMgrType.PessimistConnMgr);

        }
        private void setConnMgr(MenuItem menuItem, ConnectionMgrType mode)
        {
            mnuPessimisticMgr.Checked = false;
            mnuOptimisticMgr.Checked = false;
            mnuRollbackMgr.Checked = false;
            mnuStrictMgr.Checked = false;
            mnuCommitMgr.Checked = false;
            menuItem.Checked = true;
            _connMgrType = mode;
            string modeDesc = Enum.GetName(typeof (ConnectionMgrType), mode);
            modeDesc = modeDesc.Substring(0, modeDesc.IndexOf("ConnMgr"));
            txtConnMgrMode.Text = "Connection Mgr: " + modeDesc;
        }

        private void mnuOptimisticMgr_Click(object sender, EventArgs e)
        {
            setConnMgr(mnuOptimisticMgr, ConnectionMgrType.OptimisticConnMgr);
        }

        private void mnuStrictMgr_Click(object sender, EventArgs e)
        {
            setConnMgr(mnuStrictMgr, ConnectionMgrType.StrictConnMgr);
        }

        private void mnuCommitMgr_Click(object sender, EventArgs e)
        {
            setConnMgr(mnuCommitMgr, ConnectionMgrType.CommitTransactionConnMgr);
        }

        private void mnuRollbackMgr_Click(object sender, EventArgs e)
        {
            setConnMgr(mnuRollbackMgr, ConnectionMgrType.RollbackTransactionConnMgr);
        }
        #endregion

        #endregion
        #region Environment Handlers

        private void btnAddEnvironment_Click(object sender, EventArgs e)
        {
            try
            {
                SQLEnvironment newEnvironment = new SQLEnvironment();
                frmEnvironmentDetails newEnvironmentForm = new frmEnvironmentDetails(newEnvironment, controller.Project);
                if (newEnvironmentForm.ShowDialog() == DialogResult.OK)
                {
                    changeProjectStatus(MainFormStatus.Dirty);
                    controller.Project.Environments.Add(newEnvironment);
                    PopulateEnvironmentsList();
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(this, ex.Message, "Error");
            }

        }

        private void btnDeleteEnvironment_Click(object sender, EventArgs e)
        {
            if (lvEnvironments.SelectedItems.Count > 0)
            {
                changeProjectStatus(MainFormStatus.Dirty);
                controller.Project.Environments.Remove((SQLEnvironment)lvEnvironments.SelectedItems[0].Tag);
                PopulateEnvironmentsList();
            }
        }

        private void btnEditEnvironment_Click(object sender, EventArgs e)
        {
            EditEnvironment();
        }

        private void lvEnvironments_DoubleClick(object sender, EventArgs e)
        {
            EditEnvironment();
        }

        private void lvEnvironments_SelectedIndexChanged(object sender, EventArgs e)
        {
            Trace.WriteLine("Environment index changed");
            foreach (SQLEnvironment environment in controller.Project.Environments)
            {
                environment.IsSelected = false;
            }

            if (lvEnvironments.SelectedItems.Count > 0)
            {
                Trace.WriteLine(string.Format("Selected Index: {0}", lvEnvironments.Items.IndexOf(lvEnvironments.SelectedItems[0])));
                Trace.WriteLine(string.Format("Has {0} selected items.", lvEnvironments.SelectedItems.Count));
                SQLEnvironment env = (SQLEnvironment)lvEnvironments.SelectedItems[0].Tag;
                env.IsSelected = true;
                //TODO: Use or change control activation routine
                if (lstFolders.Items.Count > 0)
                    btnRun.Enabled = true;
            }
            else
            {
                btnRun.Enabled = false;
            }
        }

        private void EditEnvironment()
        {
            if (lvEnvironments.SelectedItems.Count == 0) return;
            SQLEnvironment environment = (SQLEnvironment)lvEnvironments.SelectedItems[0].Tag;

            environment.BeginEdit();
            frmEnvironmentDetails environmentForm = new frmEnvironmentDetails(environment, controller.Project);
            if (environmentForm.ShowDialog() == DialogResult.OK)
            {
                environment.EndEdit();
                changeProjectStatus(MainFormStatus.Dirty);
                PopulateEnvironmentsList();
            }
            else
            {
                environment.CancelEdit();
            }
        }

        internal void PopulateEnvironmentsList()
        {
            lvEnvironments.Items.Clear();

            foreach (SQLEnvironment environment in controller.Project.Environments)
            {
                ListViewItem lvItem = lvEnvironments.Items.Add(environment.Name);
                lvItem.SubItems.Add(environment.ServerName);
                lvItem.SubItems.Add(environment.DatabaseName);
                lvItem.Tag = environment;
            }
            btnRun.Enabled = false;
        }

        #endregion

        private void lstFolders_ItemCheck(object sender, ItemCheckEventArgs e)
        {
            controller.RefreshSQLProject(lstFolders, this);
        }
    }
}
